package com.ruoyi.finance.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.finance.domain.*;
import com.ruoyi.finance.domain.vo.CredentialRollupVo;
import com.ruoyi.finance.domain.vo.ProductInformationDTO;
import com.ruoyi.finance.mapper.WInvoiceGoodsDetailMapper;
import com.ruoyi.finance.mapper.WProductSalesInfoMapper;
import com.ruoyi.finance.mapper.WTemplateInfoMapper;
import com.ruoyi.finance.utils.InvoiceNumberGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.finance.mapper.WInvoiceInfoMapper;
import com.ruoyi.finance.service.IWInvoiceInfoService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
 * 进项发票Service业务层处理
 *
 * @author ruoyi
 * @date 2025-03-06
 */
@Service
public class WInvoiceInfoServiceImpl implements IWInvoiceInfoService
{
    @Resource
    private WInvoiceInfoMapper wInvoiceInfoMapper;

    @Resource
    private WTemplateInfoMapper wTemplateInfoMapper;
    @Resource
    private WInvoiceGoodsDetailMapper wInvoiceVoucherDetailsMapper;

    @Resource
    private WProductSalesInfoMapper wProductSalesInfoMapper;

    @Resource
    private  WInvoiceGoodsDetailMapper wInvoiceGoodsDetailMapper;

    @Autowired
    ThreadPoolExecutor threadPoolExecutor;

    /**
     * 查询进项发票
     *
     * @param id 进项发票主键
     * @return 进项发票
     */
    @Override
    public WInvoiceInfo selectWInvoiceInfoById(Long id)
    {
//        long workerId = 5;


        List<ProductInformationDTO> productInformationDTOList = wInvoiceInfoMapper.selectallList(id);
        //根据当前id查询出的回显数据
        WInvoiceInfo wInvoiceInfo = wInvoiceInfoMapper.selectWInvoiceInfoById(id);
        //获取商品信息

            wInvoiceInfo.setProductInformationDTOList(productInformationDTOList);
        return  wInvoiceInfo;
    }

    /**
     * 查询进项发票列表
     *
     * @param wInvoiceInfo 进项发票
     * @return 进项发票
     */
    @Override

    public List<WInvoiceInfo> selectWInvoiceInfoList(WInvoiceInfo wInvoiceInfo)
    {


        List<WInvoiceInfo> wInvoiceInfos = wInvoiceInfoMapper.selectWInvoiceInfoList(wInvoiceInfo);
        for (WInvoiceInfo invoiceInfo : wInvoiceInfos) {
          invoiceInfo.setProductInformationDTOList(wInvoiceInfoMapper.selectallList(invoiceInfo.getId()));
        }
        return wInvoiceInfos ;
    }

    /**
     * 新增进项发票
     *
     * @param wInvoiceInfo 进项发票
     * @return 结果
     */
    @Override
    @Transactional
    public int insertWInvoiceInfo(WInvoiceInfo wInvoiceInfo) {

        long workerId = 1;
//        long workerId = InvoiceNumberGenerator.getWorkerIdFromEnv();
        InvoiceNumberGenerator generator = new InvoiceNumberGenerator(
                workerId);

        String invoiceNumber = generator.generate();
        System.out.println("Generated Invoice: " + invoiceNumber);
        // 1. 设置基础信息
        String username = SecurityUtils.getUsername();
        wInvoiceInfo.setCreateUser(username);
        wInvoiceInfo.setUpdateUser(username);
//        wInvoiceInfo.setCreateTime(DateUtils.getNowDate());

        // 2. 基础校验
        validateBasicInfo(wInvoiceInfo);

        // 3. 校验发票唯一性
        validateInvoiceUniqueness(wInvoiceInfo);

        // 4. 校验商品信息并计算
        validateAndCalculateProducts(wInvoiceInfo);

        wInvoiceInfo.setId(Long.valueOf(invoiceNumber));
        // 5. 持久化数据
        int result = wInvoiceInfoMapper.insertWInvoiceInfo(wInvoiceInfo);
        insertWInvoiceGoodsDetail(wInvoiceInfo);

        return result;
    }

    private void validateBasicInfo(WInvoiceInfo wInvoiceInfo) {
        if (wInvoiceInfo.getInvoiceNumber() == null) {
            throw new RuntimeException("发票号码不能为空");
        }
        if (wInvoiceInfo.getBusinessType() == null) {
            throw new RuntimeException("业务类型不能为空");
        }
    }

    private void validateInvoiceUniqueness(WInvoiceInfo wInvoiceInfo) {
        // 使用数据库查询替代全表扫描
        int count = wInvoiceInfoMapper.countByInvoiceNumber(wInvoiceInfo.getInvoiceNumber());
        if (count > 0) {
            throw new RuntimeException("发票号重复，请输入新的凭证号码");
        }

        if (wInvoiceInfo.getInvoiceType() == 5) {
            if (StringUtils.isEmpty(wInvoiceInfo.getVinNumber())) {
                throw new RuntimeException("机动车发票需填写车牌号");
            }
            count = wInvoiceInfoMapper.countByVinNumber(wInvoiceInfo.getVinNumber());
            if (count > 0) {
                throw new RuntimeException("车牌号重复，请输入新的车牌号");
            }
        }
    }

    private void validateAndCalculateProducts(WInvoiceInfo wInvoiceInfo) {
        List<ProductInformationDTO> productList = wInvoiceInfo.getProductInformationDTOList();
        if (CollectionUtils.isEmpty(productList)) {
            throw new RuntimeException("商品信息不能为空");
        }
        // 商品金额、商品税额、价税合计
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalTax = BigDecimal.ZERO;
        BigDecimal totalTaxAmount = BigDecimal.ZERO;

        for (ProductInformationDTO product : productList) {
            validateProduct(product);
            // 商品数量、商品单价、税率
            BigDecimal quantity = new BigDecimal(product.getGoodsQuantity().toString());
            BigDecimal unitPrice = new BigDecimal(product.getUnitPrice().toString());
            BigDecimal taxRate = new BigDecimal(product.getTaxRate().toString()).divide(BigDecimal.valueOf(100));

            // 计算商品金额
            BigDecimal productAmount = quantity.multiply(unitPrice);
            // 计算税额
            BigDecimal productTax = productAmount.multiply(taxRate);
            // 价税合计
            BigDecimal productTotal = productAmount.add(productTax);
            // 商品金额、商品税额、价税合计
            totalAmount = totalAmount.add(productAmount);
            totalTax = totalTax.add(productTax);
            totalTaxAmount = totalTaxAmount.add(productTotal);
        }

        // 使用compareTo进行精确比较
        if (totalAmount.compareTo(wInvoiceInfo.getTotalAmount()) != 0) {
            throw new RuntimeException("商品金额和商品税率不匹配");
        }
        if (totalTax.compareTo(wInvoiceInfo.getTotalTax()) != 0) {
            throw new RuntimeException("商品税额计算不匹配");
        }
        if (totalTaxAmount.compareTo(wInvoiceInfo.getTotalAmountTax()) != 0) {
            throw new RuntimeException("价税合计不匹配");
        }
    }

    private void validateProduct(ProductInformationDTO product) {
        if (product.getGoodsQuantity() == null || product.getUnitPrice() == null) {
            throw new RuntimeException("商品数量和单价不能为空");
        }
        if (product.getTaxRate() == null) {
            throw new RuntimeException("商品税率不能为空");
        }
        if (product.getGoodsQuantity().doubleValue() <= 0
                || product.getUnitPrice().doubleValue() <= 0) {
            throw new RuntimeException("商品数量和单价必须大于0");
        }
    }
    /**
     * 修改进项发票
     *
     * @param wInvoiceInfo 进项发票
     * @return 结果
     */
    @Override
    public int updateWInvoiceInfo(WInvoiceInfo wInvoiceInfo)
    {

        wInvoiceInfo.setUpdateTime(DateUtils.getNowDate());
        return wInvoiceInfoMapper.updateWInvoiceInfo(wInvoiceInfo);
    }

    /**
     * 批量删除进项发票
     *
     * @param ids 需要删除的进项发票主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteWInvoiceInfoByIds(Long[] ids)
    {
        wInvoiceInfoMapper.deleteWInvoiceVoucherDetailsByInvoiceModuleIds(ids);

        return wInvoiceInfoMapper.deleteWInvoiceInfoByIds(ids);
    }

    /**
     * 删除进项发票信息
     *
     * @param id 进项发票主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteWInvoiceInfoById(Long id)
    {
        wInvoiceInfoMapper.deleteWInvoiceVoucherDetailsByInvoiceModuleId(id);
        return wInvoiceInfoMapper.deleteWInvoiceInfoById(id);
    }

    @Override
    public void export(HttpServletResponse response, WInvoiceInfo wInvoiceInfo) {
        List<WInvoiceInfo> list = wInvoiceInfoMapper.selectWInvoiceInfoList(wInvoiceInfo);
        for (WInvoiceInfo invoiceInfo : list) {
            invoiceInfo.setProductInformationDTOList(wInvoiceInfoMapper.selectallList(invoiceInfo.getId()));
        }
        ExcelUtil<WInvoiceInfo> util = new ExcelUtil<WInvoiceInfo>(WInvoiceInfo.class);
        try {
            int batchSize = 1000; // 每个线程处理的数据量
            List<Future<List<WInvoiceInfo>>> futures = new ArrayList<>();

            // 数据分片
            for (int i = 0; i < list.size(); i += batchSize) {
                int end = Math.min(i + batchSize, list.size());
                List<WInvoiceInfo> subList = list.subList(i, end);

                // 提交任务到线程池
                Future<List<WInvoiceInfo>> future = threadPoolExecutor.submit(() -> {
                    List<WInvoiceInfo> processedData = new ArrayList<>();

                    for (WInvoiceInfo dto : subList) {
                        try {
                            // 1. 数据格式校验和转换
                            if (dto != null) {
                                // 2. 总金额计算和汇总
                                // 确保金额字段不为空
                                if (dto.getTotalAmount() == null) {
                                    dto.setTotalAmount(BigDecimal.valueOf(0.0));
                                }
                                if (dto.getTotalAmountTax() == null) {
                                    dto.setTotalAmountTax(BigDecimal.valueOf(0.0));
                                }
                                // 3. 税额计算和汇总
                                if (dto.getTotalTax() == null){
                                    dto.setTotalTax(BigDecimal.valueOf(0.0));
                                }


                                // 5. 性能优化处理
                                // 使用批量处理减少内存占用
                                processedData.add(dto);
                            }
                        } catch (Exception e) {
                            // 记录异常但继续处理其他数据
                            e.printStackTrace();
                            System.out.println("处理异常：" + e.getMessage());
                        }
                    }

                    return processedData;
                });
                futures.add(future);
            }

            // 等待所有任务完成并合并结果
            List<WInvoiceInfo> processedList = new ArrayList<>();
            for (Future<List<WInvoiceInfo>> future : futures) {
                processedList.addAll(future.get());
            }

            // 导出到Excel
            util.exportExcel(response, processedList, "凭证详情数据");

        } catch (Exception e) {

            throw new RuntimeException("导出失败：" + e.getMessage());
        }


    }

    public void insertWInvoiceGoodsDetail(WInvoiceInfo wInvoiceInfo){


        //获取循环的数据
        List<ProductInformationDTO> list = wInvoiceInfo.getProductInformationDTOList();
        //获取主表添加自增的id
        Long id = wInvoiceInfo.getId();
        //判断数据是否是空的
        if (StringUtils.isNotNull(list)){
            //创建arrayList集合储存循环的数据进行一次性添加
            ArrayList<WInvoiceGoodsDetail> arrayList = new ArrayList<>();
            for (ProductInformationDTO productInformationDTO : list) {

//                WInvoiceGoodsDetail wInvoiceGoodsDetail = new WInvoiceGoodsDetail();

                WInvoiceGoodsDetail build = WInvoiceGoodsDetail.builder().id(productInformationDTO.getId())
                        //设置发票id
                        .invoiceId(id)
                        //用户id
                        .userId(SecurityUtils.getUserId())
                        //模版id
                        .templateId(wInvoiceInfo.getTemplateInfoId())
                        //设置商品id
                        .goodsId(productInformationDTO.getGoodsId())
                        //商品数量
                        .goodsQuantity(productInformationDTO.getGoodsQuantity())
                        //商品金额
                        .goodsAmount(productInformationDTO.getGoodsAmount())
                        //商品税
                        .goodsTax(productInformationDTO.getGoodsTax())
                        //创建人
                        .createUser(SecurityUtils.getUsername())
                        //更新人
                        .updateUser(SecurityUtils.getUsername())
                        .build();


                wInvoiceVoucherDetailsMapper.insert(build);
            }
//            if (arrayList.size() > 0){
////                wInvoiceInfoMapper.batchWInvoiceGoodsDetail(arrayList);
//            }
        }


    }

    /**
     * @Author TianJiaKuan
     * @Description //TODO 测试定义的不重复编号
     * @Date 11:22 2025/3/10
     * @Param [args]
     * @return void
     **/
    public static void main(String[] args) {
        // 从环境变量获取实例ID（需部署时配置）
        long workerId = InvoiceNumberGenerator.getWorkerIdFromEnv();
        InvoiceNumberGenerator generator = new InvoiceNumberGenerator(workerId);

        String invoiceNumber = generator.generate();
        System.out.println("Generated Invoice: " + invoiceNumber);
    }

}
